package org.cogaen.java2d.xml;

import java.awt.Font;

import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

public class FontParser {

	public static final int DEFAULT_SIZE = 10;
	public static final String DEFAULT_NAME = null;
	public static final int DEFAULT_STYLE = Font.PLAIN;
	private static final String FONT_ELEMENT = "font";
	private static final String SIZE_ATTRIBUTE = "size";
	private static final String BOLD_ATTRIBUTE = "bold";
	private static final String ITALIC_ATTRIBUTE = "italic";
	
	private String name;
	private int style;
	private int size;
	
	public static ResetableStreamFilter createFilter(String fontName) {
		return new ElementFilter(FONT_ELEMENT, fontName);
	}

	public static boolean isStart(XMLStreamReader reader) {
		return reader.isStartElement() && FONT_ELEMENT.equals(reader.getLocalName());
	}
	
		
	public void parse(XMLStreamReader reader) throws XMLStreamException, ParseException {
		reset();
		if (isStart(reader)) {
			parseStyle(reader);
			parseSize(reader);
			parseName(reader);
		} else {
			throw new ParseException("xml element not found");
		}
	}
		
	private void reset() {
		this.name = null;
		this.style = DEFAULT_STYLE;
		this.size = DEFAULT_SIZE;
	}
	
	private void parseName(XMLStreamReader reader) throws XMLStreamException, ParseException {
		
		this.name = DEFAULT_NAME;
		
		while (reader.hasNext()) {
			int event = reader.next();
			
			switch (event) {
			case XMLStreamConstants.CHARACTERS:
				this.name = reader.getText();
				break;

			case XMLStreamConstants.START_ELEMENT:
				throw new ParseException("unexpected new element '" + reader.getLocalName() + "'");
				
			case XMLStreamConstants.END_DOCUMENT:
				throw new ParseException("unexepcted end of document");
				
			case XMLStreamConstants.END_ELEMENT:
				if (FONT_ELEMENT.equals(reader.getLocalName())) {
					return;
				} else {
					throw new ParseException("unexpected end of element '" + reader.getLocalName() + "'");					
				}
			}			
		}		
	}

	private void parseSize(XMLStreamReader reader) throws ParseException {
		String str = reader.getAttributeValue(null, SIZE_ATTRIBUTE);
		
		if (str == null) {
			this.size = DEFAULT_SIZE;
			return;
		}
		
		try {
			this.size = Integer.parseInt(str);
		} catch (NumberFormatException e) {
			this.size = DEFAULT_SIZE;
			throw new ParseException("invalid font size '" + str + "'");
		}		
	}

	private void parseStyle(XMLStreamReader reader) {
		this.style = 0;
		
		String str = reader.getAttributeValue(null, BOLD_ATTRIBUTE);
		if (str != null && str.equalsIgnoreCase("true")) {
			this.style = Font.BOLD;
		}
		
		str = reader.getAttributeValue(null, ITALIC_ATTRIBUTE);
		if (str != null && str.equalsIgnoreCase("true")) {
			this.style |= Font.ITALIC;
		}
		
		if (this.style == 0) {
			this.style = Font.PLAIN;
		}
	}

	
	public String getName() {
		return name;
	}
	
	public int getStyle() {
		return style;
	}
	
	public int getSize() {
		return size;
	}
}
